/**
 * 
 */
package org.adempiere.apps.graph;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.ComponentOrientation;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Properties;
import java.util.TreeMap;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.KeyStroke;

import layout.TableLayout;

import org.adempiere.apps.graph.BSCViewDashboard.ValueComparator;
import org.adempiere.plaf.AdempierePLAF;
import org.compiere.apps.ADialog;
import org.compiere.apps.AEnv;
import org.compiere.apps.AppsAction;
import org.compiere.apps.ConfirmPanel;
import org.compiere.apps.IProcessParameter;
import org.compiere.apps.ProcessCtl;
import org.compiere.apps.ProcessParameterPanel;
import org.compiere.apps.Waiting;
import org.compiere.apps.form.FormFrame;
import org.compiere.apps.form.FormPanel;
import org.compiere.grid.ed.AutoCompletion;
import org.compiere.grid.ed.VComboBox;
import org.compiere.model.I_BPM_Form;
import org.compiere.model.I_BPM_Project;
import org.compiere.model.MBPMProjectLine;
import org.compiere.model.MBSCCard;
import org.compiere.model.MBSCDashboard;
import org.compiere.model.MPeriod;
import org.compiere.model.MRole;
import org.compiere.swing.CButton;
import org.compiere.swing.CComboBox;
import org.compiere.swing.CPanel;
import org.compiere.swing.CScrollPane;
import org.compiere.util.CLogger;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.util.KeyNamePair;
import org.compiere.util.Msg;
import org.compiere.process.BSCCardDiagram;
import org.compiere.process.ProcessInfo;
import org.compiere.process.ProcessInfoParameter;

import extend.org.compiere.utils.Util;

/**
 * @author Y.Ibrayev
 *
 */
public class BSCViewDashboard1 extends CPanel  implements FormPanel, ActionListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -3965861742626702550L;
	private static CLogger log = CLogger.getCLogger (BSCViewDashboard1.class);
	private int m_WindowNo = 0;
	private FormFrame m_frame;
	private ConfirmPanel confirmPanel = new ConfirmPanel();
	private CPanel mainPanel = new CPanel();
	private CPanel loadPanel = new CPanel(new FlowLayout(FlowLayout.LEADING));
	private CPanel dashboardView = new CPanel();
	private BSCCardPanelNew panel = new BSCCardPanelNew(null);  
	private VComboBox cbPeriod = new VComboBox();
	private ArrayList<JButton> buttons = new ArrayList<JButton>(); 
	private ArrayList<MBSCDashboard> cards = new ArrayList<MBSCDashboard>(); 
	private MPeriod period = null;
	private int currentCard = -1;
	private CButton diagramm = new CButton("Графическое отображение показателей");
	private CButton buttonRefresh = new CButton("Обновить");
	private VComboBox fBPartner = new VComboBox(getBPartners());
	private CButton buttonPrint = new CButton();

	/* (non-Javadoc)
	 * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
	 */
	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().equals(ConfirmPanel.A_OK))
			dispose();
		else if (e.getSource() == cbPeriod && cbPeriod.getSelectedItem() != null) {
			KeyNamePair knp = (KeyNamePair) cbPeriod.getSelectedItem();
			setPeriod(new MPeriod(Env.getCtx(),knp.getKey(),null));
			//initCards();
			reDrawPanel();
		} else if (e.getSource() == diagramm){
			viewDiagramm();
		} else if (e.getActionCommand().equals(buttonRefresh.getName())) {
			//setCard(null);
			//setCard(MBSCCard.get(((KeyNamePair) fBPartner.getSelectedItem()).getKey(), period.getC_Period_ID()));
			reDrawPanel();
		} else if (e.getActionCommand().equals(buttonPrint.getName())) {
			printCard();
			
		} else if(e.getSource().equals(fBPartner) && fBPartner.getSelectedItem() != null) {
			int C_BPartner_ID = 0;
			int C_Period_ID = 0;
			KeyNamePair knp = (KeyNamePair) fBPartner.getSelectedItem();
			C_BPartner_ID = knp.getKey();
			
			C_Period_ID  = period.getC_Period_ID();
			
			MBSCCard card = MBSCCard.get(C_BPartner_ID, C_Period_ID);
			
			setCard(card);
			
		} else if (e.getSource() instanceof JButton){
			for(int i = 0 ; i < getButtons().size(); i++) {
				if (e.getSource() == getButtons().get(i)) {
					currentCard = i;
					reDrawPanel();
				}
			}
		}
	}

	
	private void printCard() {
		if (getCard() != null) {
			setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			String nameProcess = "BSC_ReportBSCCard"; 
			Properties m_ctx = Env.getCtx();
			int AD_Process_ID = Util.getAD_Process(nameProcess);
			ProcessInfo pi = new ProcessInfo ("BSC Card", AD_Process_ID);
			//  Prepare Process
			pi.setAD_User_ID (Env.getAD_User_ID(m_ctx));
			pi.setAD_Client_ID(Env.getAD_Client_ID(m_ctx));
			List<ProcessInfoParameter> po = new ArrayList<ProcessInfoParameter>();
			po.clear();
			po.add(new ProcessInfoParameter(MBSCCard.COLUMNNAME_AD_Org_ID, new BigDecimal(getCard().getAD_Org_ID()),null,"",""));
			po.add(new ProcessInfoParameter(MBSCCard.COLUMNNAME_AD_Client_ID, new BigDecimal(getCard().getAD_Client_ID()),null,"",""));
			po.add(new ProcessInfoParameter(MBSCCard.COLUMNNAME_C_Period_ID, new BigDecimal(getCard().getC_Period_ID()),null,"",""));
			po.add(new ProcessInfoParameter(MBSCCard.COLUMNNAME_C_BPartner_ID, new BigDecimal(getCard().getC_BPartner_ID()),null,"",""));
				//
			ProcessInfoParameter[] pp = new ProcessInfoParameter[po.size()];
			po.toArray(pp);
			pi.setParameter(pp);
				//	Execute Process
			ProcessParameterPanel pu = new ProcessParameterPanel(0, pi);
			ProcessCtl.process(null, 0, (IProcessParameter) pu, pi, null);
			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		}
	}

	/**
	 * 
	 */
	private void viewDiagramm() {
		if (currentCard < 0) {
			ADialog.info(25, this, "Виберите карту ССП");
			return;
		}
		MBSCCard card = cards.get(currentCard).getCard();
		if (card == null) {
			ADialog.info(25, this, "Карта ССП не найден");
			return;
		}
		FormFrame myWindow = new FormFrame(Env.getWindow(0).getGraphicsConfiguration());
		if (myWindow.openForm(BSCCardDiagram.getBSCViewCardLine())) {
			BSCViewCardLine view = (BSCViewCardLine) myWindow.getFormPanel();
			if (card.getBSC_Card_ID() > 0) {
				view.load(card.getBSC_Card_ID(),0);
			}
			AEnv.addToWindowManager(myWindow);
			AEnv.showCenterScreen(myWindow);
			myWindow.setVisible(true);
			myWindow.setFocusableWindowState(true);
			myWindow.toFront();
		}
	}

	/**
	 * 
	 */
	private void reDrawPanel() {
		MBSCCard card = (currentCard > -1 ? cards.get(currentCard).getCard() : null); 
		setCard(card);
	}

	/* (non-Javadoc)
	 * @see org.compiere.apps.form.FormPanel#init(int, org.compiere.apps.form.FormFrame)
	 */
	@Override
	public void init(int WindowNo, FormFrame frame) {
		log.fine(this.getName());
		m_WindowNo = WindowNo;
		m_frame = frame;
		m_frame.setSize(1200, 600);
		//m_frame.setPreferredSize(new Dimension(1200,600));
		//m_frame.setMinimumSize(new Dimension(1200,600));
		
		initCards();
		
		initLoadPanel();
		initDashboardView();
		initMainPanel();
		
		m_frame.getContentPane().add(loadPanel, BorderLayout.NORTH);
		m_frame.getContentPane().add(dashboardView, BorderLayout.WEST);
		
		CScrollPane scroll =  new CScrollPane(mainPanel);
		Dimension d = new Dimension(850,400);
		scroll.setSize(d);
//		scroll.setPreferredSize(d);
		scroll.setMinimumSize(d);
		m_frame.getContentPane().add(scroll, BorderLayout.CENTER);

		confirmPanel.addActionListener(this);
		m_frame.getContentPane().add(confirmPanel, BorderLayout.SOUTH);
		
		initFirstLook();
	}

	private void initFirstLook() {
		currentCard = 0;
		setPeriod(getCurrentPeriod());
		reDrawPanel();
	}

	private MPeriod getCurrentPeriod() {
		String sql = "";
		return null;
	}

	/* (non-Javadoc)
	 * @see org.compiere.apps.form.FormPanel#dispose()
	 */
	@Override
	public void dispose() {
		if (m_frame != null)
			m_frame.dispose();
		m_frame = null;
		removeAll();
	}

	private void initLoadPanel() {
		JLabel lbl = new JLabel("Период:");
		loadPanel.add(lbl);
		loadPanel.add(initCbPeriod());
		loadPanel.add(initButtonPrint());
		loadPanel.add(initButtonRefresh());
		loadPanel.add(initDiagramm());
		lbl = new JLabel("Сотрудник:");
		loadPanel.add(lbl);
		loadPanel.add(initfBPartner());
	}

	private Component initfBPartner() {
		fBPartner.setBackground(AdempierePLAF.getInfoBackground());
		fBPartner.addActionListener(this);		
		return fBPartner;
	}

	private Component initButtonRefresh() {
		JMenu mFile = AEnv.getMenu("File");
		AppsAction aReport = addAction("Refresh", mFile, KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0),	false);
		buttonRefresh = (CButton) aReport.getButton();
//		buttonRefresh.addActionListener(this);
		return buttonRefresh;
	}

	private Component initButtonPrint() {
		
		JMenu mFile = AEnv.getMenu("File");
		AppsAction aReport = addAction("Report", mFile, KeyStroke.getKeyStroke(KeyEvent.VK_F11, 0),	false);
		buttonPrint = (CButton) aReport.getButton();
		buttonPrint.setText("Печать");
//		buttonPrint.addActionListener(this);
		return buttonPrint;
	}
	
	/**
	 * @return
	 */
	private Component initDiagramm() {
		diagramm.addActionListener(this);
		return diagramm;
	}

	private CComboBox initCbPeriod() {
		String sql = MRole.getDefault().addAccessSQL(
				"SELECT C_Period_ID, Name FROM C_Period "
				+ "WHERE C_Year_ID IN "
				+ "(SELECT C_Year_ID FROM C_Year "
				+ "WHERE C_Calendar_ID IN "
				+ "(SELECT C_Calendar_ID "
				+ "FROM C_Calendar WHERE Name like 'BSC%')) "
				+ "ORDER BY 2",
				"C_Period", MRole.SQL_NOTQUALIFIED, MRole.SQL_RO);	//	all
		KeyNamePair[] pp1 = DB.getKeyNamePairs(sql, true);
		cbPeriod = new VComboBox(pp1);
		AutoCompletion.enable(cbPeriod);
		cbPeriod.addActionListener(this);
		return cbPeriod;
	}
	
	private void initMainPanel() {
		mainPanel.add(panel);
	}

	/**
	 * 
	 */
	private void initDashboardView() {
		
		GridBagLayout gbLayout = new GridBagLayout(); 
		
		JPanel grid = new JPanel(gbLayout);
		dashboardView.setLayout(new FlowLayout(FlowLayout.LEFT));
		GridBagConstraints gbc = new GridBagConstraints(); 
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		gbc.gridx = 0;
		int y = 0;
		for(JButton button : getButtons()) {
			gbc.gridy = y;
			grid.add(button,gbc);
			button.addActionListener(this);
			y++;
		}
		dashboardView.add(grid);
	}

	public ArrayList<JButton> getButtons() {
		return buttons;
	}

	public void setButtons(ArrayList<JButton> buttons) {
		this.buttons = buttons;
	}

	private void initCards() {

		MBSCDashboard[] listDB = MBSCDashboard.getDashboard((period == null ? 0 : period.getC_Period_ID()));
		
		ValueComparator bvc =  new ValueComparator(listDB);

		TreeMap<MBSCDashboard,MBSCCard> dbmap = new TreeMap<MBSCDashboard,MBSCCard>(bvc);  
		for(MBSCDashboard item : listDB) {
			dbmap.put(item, item.getCard());
		}
		cards.clear();
		buttons.clear();
		
		for(MBSCDashboard item: dbmap.keySet()) {
			cards.add(item);
			JButton button = new JButton("<html>" + (item.getHR_Job_ID() > 0 ? item.getHR_Job().getName() : "---") + "<br>("+item.getC_BPartner().getName()+")</html>");
			buttons.add(button);
		}
	}
	
	public MPeriod getPeriod() {
		return period;
	}

	public void setPeriod(MPeriod period) {
		if (period != null) {
			for(MBSCDashboard item: cards) {
				item.setPeriod(period);
			}
		}
		this.period = period;
	}

	class ValueComparator implements Comparator<MBSCDashboard> {

		MBSCDashboard[] base;
	    public ValueComparator(MBSCDashboard[] base) {
	        this.base = base;
	    }

	    // Note: this comparator imposes orderings that are inconsistent with equals.    
	    public int compare(MBSCDashboard a, MBSCDashboard b) {
	    	if (a != null && b != null) {
	    		if (a.getNumberOfRuns() < b.getNumberOfRuns())
	    			return -1;
	    		else if (a.getNumberOfRuns() > b.getNumberOfRuns())
	    			return 1;
	    		else
	    			return 0;
	    	} else {
	    		return 0;
	    	}
	    }
	}
	/**
	 * @return
	 */
	private KeyNamePair[] getBPartners() {
		String sql = "SELECT C_BPartner_ID \n"
				   + "     , Name \n"
				   + "FROM C_BPartner \n"
				   + "WHERE C_BPartner_ID IN (SELECT C_BPartner_ID FROM BSC_Card WHERE IsActive = 'Y' AND AD_Client_ID = ?)";
		int AD_Client_ID = Env.getAD_Client_ID(Env.getCtx());
		List<Object> params = new ArrayList<Object>();
		params.add(new Integer(AD_Client_ID));
		KeyNamePair[] result = DB.getKeyNamePairs(sql, true, params);
		return result;
	}
	
	public void setCard(MBSCCard card) {
		if (card != null) {
			panel.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
			if (card.getC_Period_ID() != (period != null ? period.getC_Period_ID() : 0)) {
				setPeriod(new MPeriod(Env.getCtx(),card.getC_Period_ID(),null));
				cbPeriod.setValue(period.getC_Period_ID());
				cbPeriod.repaint();
			}
			if(card.getC_BPartner_ID() != (fBPartner.getValue() != null ? ((Integer)fBPartner.getValue()).intValue() : 0)) {
				fBPartner.setValue(new Integer(card.getC_BPartner_ID()));
				fBPartner.repaint();
			}
			panel.setCard(card);
			panel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
		}
	}

	private AppsAction addAction (String actionName, JMenu menu, KeyStroke accelerator, boolean toggle)
	{
		AppsAction action = new AppsAction(actionName, accelerator, toggle);
		if (menu != null)
			menu.add(action.getMenuItem());
		action.setDelegate(this);

		//	Key Strokes
		if (accelerator != null)
		{
			getInputMap(WHEN_IN_FOCUSED_WINDOW).put(accelerator, actionName);
			getActionMap().put(actionName, action);
		}
		//
		return action;
	}	//	addAction
	
	public MBSCCard getCard() {
		return panel.getCard();
	}

}
